import axios from "axios";
const fs = require("fs");
import moment from "moment";
const path = require("path");
const chalk = require("chalk");
// const axios = require("axios");
const FormData = require("form-data");
// md5加密库
const crypto = require("crypto");
const smCrypto = require("sm-crypto");
// bash子线程
const { exec } = require("child_process");

// 执行当前文件命令行传参
// 模板编号：args[0] (不带m,如3001)
// 打包环境：args[1] (alpha/prod)
// 上传环境: args[2] (如a/b/c/d/e)
// 打包输出的文件夹名:prod=>arg[2];alpha=>arg[3] (如dist)
// 指定某环境拿template.json与.zip一起压缩：prod=>arg[3];alpha=>arg[4])   (如a/b/c/d/e)
const args = process.argv.slice(2);
// 当前需要打zip包的模板编号
const templateId = args[0];
// 打包环境
const buildEnv = args[1];
// 上传环境/使用打包工具的环境
const upLoadEvn = args[2].length === 1 ? `pl4${args[2]}` : args[2];
// 打包输出的文件夹名，默认dist
const outputDir = args[3] || "dist";
// 指定某环境拿template.json与.zip一起压缩
const downTemplateEvn =
  args[4] && (args[4].length === 1 ? `pl4${args[4]}` : args[4]);
// 区分活动包和功能包
const packageName = /^\d/.test(templateId) ? `m${templateId}` : templateId;
// 当前项目目录
const projectDir = process.env.INIT_CWD;
// 测试环境alpha 在运行完后是否删除zip包，默认打开
const isalphaDeleteZIP = true;
// 用户信息=>拿token用
const userInfo = {
  mobile: "13010896676",
  purview: true,
  tenantId: "ccb",
  unit: "010210007",
  userId: "86620731",
  username: "曾丹",
};
// 用户额外信息=>拿CCBAuthorization用
const userAnotherInfo = {
  bgtMgrDeptId: "010210007",
  createdById: "86620731",
  loginTime: new Date().getTime(),
};
let token;
// console.log(
//   chalk.blue.bold(
//     "-------::生产打包命令新增了参数(使用工具包环境),如打生产包报错404,请补全命令参数,具体使用方式请看README.md"
//   )
// );
// console.log(
//   chalk.red.bold(
//     "-------::此版本可自动同步远程工具包文件,再无需手动替换本地脚本!(如打包后autoZipNode.js发生本地变更,请接受并提交它)"
//   )
// );
console.log(
  chalk.red.bold("\n项目:dop-front-h5  分支:autoZipNode  使用方式:README.md")
);
console.log(
  chalk.blue.bold(
    "----------------------------------------------------------------------------"
  )
);
console.log(
  chalk.blue.bold(
    `模板编号:${templateId}  打包环境:${buildEnv}  输出文件夹:${outputDir}  ${
      buildEnv === "alpha"
        ? `(工具包/上传)环境:${upLoadEvn}`
        : `工具包环境:${upLoadEvn}`
    }  ${
      downTemplateEvn
        ? `template.json下载环境:${downTemplateEvn}`
        : "--使用本地template.json打包(如果有)--"
    }`
  )
);
console.log(
  chalk.blue.bold(
    "----------------------------------------------------------------------------"
  )
);
// 存在遗留的打包文件夹，重命名，防止与下一步重命名冲突
outputDir !== `${packageName}` &&
  fs.existsSync(`${packageName}`) &&
  fs.renameSync(
    `${packageName}`,
    `${packageName}-${new Date().getTime()}`,
    err => console.log(err)
  );
// 将webpack打包后的文件夹重命名
fs.renameSync(outputDir, `${packageName}`, err => console.log(err));
// 配置了template.json的下载环境，则先下载指定环境的template.json,不然直接开始加密压缩
downTemplateEvn ? downLoadTemplateZip() : zipFile();

// 下载接口，拿template.json
async function downLoadTemplateZip() {
  const loginToken = await getCCBAuthorization();
  console.log(`成功获取登录token，继续获取用户token...`);
  token = await getToken(downTemplateEvn);
  console.log(
    `成功获取用户token，开始下载 ${downTemplateEvn} 环境 ${packageName} 模板包...`
  );
  // 下载的url
  const url = `http://128.196.132.200/api-${downTemplateEvn}-dev/content/avtivityTemplate/export/${templateId}?onlyJson=true`;
  return axios({
    url,
    method: "get",
    responseType: "arraybuffer",
    headers: {
      CCBAuthorization: `Bearer ${loginToken}`,
      "x-user-token": token,
    },
  })
    .then(res => {
      if (res.data.code) {
        console.log(res.data);
        console.loe("下载失败，不管template.json了，直接压缩！");
        zipFile(true);
      } else {
        fs.writeFileSync("template.json", res.data);
        zipFile();
      }
    })
    .catch(e => {
      console.log("err：", e);
    });
}

// 压缩文件
function zipFile(failGetTemplate) {
  downTemplateEvn && !failGetTemplate
    ? console.log(`开始使用${downTemplateEvn}环境template.json加密压缩...`)
    : console.log(`开始使用本地template.json(如果有)加密压缩...`);
  // -m 每次压缩完，删除对应文件和文件夹
  exec(
    `zip -r -m -P 123456 ${packageName}.zip ${packageName} template.json`,
    error => {
      if (error) {
        console.log(`压缩失败:${error}`);
        return;
      }
      console.log(`加密压缩得到:${packageName}.zip`);
      md5File();
    }
  );
}
// 给.zip加md5值
function md5File() {
  console.log("开始获取md5值...");
  const buffer = fs.readFileSync(path.join(projectDir, `${packageName}.zip`));
  const hash = crypto.createHash("md5");
  hash.update(buffer, "utf8");
  const md5 = hash.digest("hex");
  const finalName = `${templateId}-${md5}.zip`;
  fs.renameSync(`${packageName}.zip`, finalName);
  console.log("已完成zip重命名得到:", finalName);
  if (buildEnv === "alpha") {
    upLoadFile(finalName);
  } else {
    downTemplateEvn
      ? console.log(
          chalk.red.bold(
            `已完成操作，得到由${downTemplateEvn}环境下的template.json组合的生产包，请自行上传！`
          )
        )
      : console.log(
          chalk.red.bold(
            `已完成操作，得到由本地环境template.json(如果有)组合的生产包，请自行上传！`
          )
        );
    console.log(
      chalk.blue.bold(
        `-------:  ${moment(new Date()).format(
          "YYYY-MM-DD HH:mm:ss"
        )}  :-------`
      )
    );
  }
}
// 上传模板包
async function upLoadFile(filename) {
  let data = new FormData();
  let templateZipFile = fs.createReadStream(filename);
  data.append("file", templateZipFile);
  const len = await new Promise((resolve, reject) =>
    data.getLength((err, length) => (err ? reject(err) : resolve(length)))
  );
  const upLoadToken =
    upLoadEvn === downTemplateEvn && downTemplateEvn
      ? token
      : await getToken(upLoadEvn);
  if (!upLoadToken)
    return console.log(`获取用户token失败,是不是服务器炸了呢？`);
  console.log(`成功获取用户token，开始上传模板包至 ${upLoadEvn} 环境...`);
  // 上传的url
  const url = `http://128.196.132.200/api-${upLoadEvn}-dev/content/avtivityTemplate/import`;
  axios({
    url,
    data,
    method: "post",
    maxBodyLength: Infinity,
    headers: {
      "Content-Type": `multipart/form-data;boundary=${data.getBoundary()}`,
      "Content-length": len,
      "x-user-token": upLoadToken,
    },
  })
    .then(res => {
      if (res.data.code === 200) {
        console.log(
          chalk.red.bold(
            `已将${filename}上传至 ${upLoadEvn} 环境!${
              downTemplateEvn
                ? `(${downTemplateEvn}环境template.json)`
                : "(本地template.json)"
            }`
          )
        );
        // 是否清除zip包
        if (buildEnv === "alpha" && isalphaDeleteZIP) {
          fs.unlinkSync(filename);
          console.log(
            chalk.blue.bold(
              `-------:  ${moment(new Date()).format(
                "YYYY-MM-DD HH:mm:ss"
              )}  :-------`
            )
          );
        }
      } else {
        console.log(res.data);
      }
    })
    .catch(e => {
      console.log("err：", e);
    });
}
// 获取上传接口需要的token
function getToken(evn) {
  console.log("开始获取用户token...");
  const url = `http://128.196.132.200/api-${evn}-dev/sys/check`;
  return axios({
    url,
    data: userInfo,
    method: "post",
  })
    .then(res => {
      if (res.data.code === 200) {
        return res.data.data.token;
      } else console.log(res);
    })
    .catch(e => {
      console.log("err：", e);
    });
}
// 获取下载接口需要的token
function getCCBAuthorization() {
  // 获取CCBAuthorization的url,下载文件需要
  const url = `http://128.196.132.200/api-${downTemplateEvn}-dev/content/rbac/system/check`;
  // 拿CheckData
  const getCheckData = data => {
    const sm2PublicKey =
      "044140d69205a3804e87a9cd9023042c36c48b76f877186c08087ac6f93c2409c4cd8dbbf4915cce4ebc03341ac3042e44b368e9bbe60782dcf06e93bba6d647b8";
    const finData = Object.entries(data).reduce(
      (finData, next, index) =>
        (finData += `${index ? `&` : ""}${next[0]}=${next[1]}`),
      ""
    );
    return "04" + smCrypto.sm2.doEncrypt(finData, sm2PublicKey, 1);
  };
  console.log("开始获取登录token...");
  return axios({
    url,
    data: { checkData: getCheckData(userAnotherInfo) },
    method: "post",
  })
    .then(res => {
      if (res.data.code === 200) {
        return res.data.token;
      } else throw new Error(res.message);
    })
    .catch(e => {
      console.log("err：", e);
    });
}
